<script setup lang="ts">
import Konva from 'konva';
import type {KonvaCircle, KonvaImage} from "~/utils/konvaUtils";
import {CustomerServiceOutlined, CommentOutlined} from '@ant-design/icons-vue';
import {nanoid} from 'nanoid'
import UploadButton from "~/components/common/UploadButton.vue";
import {UploadOutlined,DragOutlined,HighlightOutlined} from '@ant-design/icons-vue'
import {blobtoFile, useUtilsUploadFileToOSS} from "~/utils/FileUtils";

const freeDraw = ref(false)
watch(freeDraw, () => {
  if (!freeDraw.value) {
    baseLayer.value.getStage().children.forEach(item => {
      item.draggable(true)
    })
  }
})
type DrawMode = 'brush' | "eraser" | "line"
//编辑模式，变换、裁剪
type EditMode = 'transform' | 'clip'
const brushMode = ref<DrawMode>('eraser')
const editMode = ref<EditMode>('clip')
const stage = ref()
const baseLayer = ref()
const handleLayer = ref()
const maskLayer = ref()
const sceneWidth = 600
const sceneHeight = 800
const configKonva = ref({
  width: sceneWidth,
  height: sceneHeight,
  scale: {x: 1, y: 1},
  draggable: false,
})
const baseLayerConfig = ref({
  name: 'baseLayer',
  draggable: false,
})
const handleLayerConfig = ref({
  name: 'handleLayer',
  draggable: false,
})
const maskLayerConfig = ref({
  name: 'maskLayer',
  draggable: false,
  // opacity:0.5
})
onMounted(() => {
  // const url = 'https://wangbo0808.oss-cn-shanghai.aliyuncs.com/aidraw/00001.png';
  // handleLoadImage(url)
  handleFitStageIntoParentContainer()
})


const handldDrawLine = () => {
  const configLine = ref({
    points: [0, 0, 100, 200, 300, 300],
    tension: 0,
    closed: true,
    stroke: 'white',
    fill: 'black',
    strokeWidth: 10
  })
  baseLayer.value.getStage().add
}

//上传图片
const uploadurl = ref('')
watch(uploadurl, () => {
  if (uploadurl.value) {
    handleLoadImage(uploadurl.value)
  }
})
const handleLoadImage = (url: string, name?: string) => {
  const imageObj = new Image();
  imageObj.src = url
  imageObj.onload = () => {
    console.log('imageObj onload', imageObj.width)
    Konva.Image.fromURL(url, function (darthNode) {
      //计算尺寸默认铺满
      const scale = Math.min(configKonva.value.width / imageObj.width, configKonva.value.height / imageObj.height)
      darthNode.setAttrs({
        name: name || nanoid(),
        x: 0,
        y: 0,
        scaleX: scale / configKonva.value.scale.x,
        scaleY: scale / configKonva.value.scale.x,
        // cornerRadius: 20,
      });
      darthNode.on('dblclick dbltap', function () {
        this.destroy();
      });
      darthNode.on('mouseover', function () {
        document.body.style.cursor = 'pointer';
      });
      darthNode.on('mouseout', function () {
        document.body.style.cursor = 'default';
      });
      baseLayer.value.getStage().add(darthNode);
      handleFitStageIntoChildContainer()
    });
  }
}

const transformer = ref()
const selectedShapeName = ref('')
const brush = ref({
  name: 'brush1',
  x: 0,
  y: 0,
  radius: 40/configKonva.value.scale.x,
  fill: "black",
} as KonvaCircle)
const handleStageMouseDown = (e) => {
  // clicked on stage - clear selection
  console.log('点击事件', e.target)
  if (freeDraw.value) {
    //自由画布模式
    // console.log(baseLayer.value.getStage().children)
    // maskLayer.value.getStage().show()
    baseLayer.value.getStage().children.forEach(item => {
      item.draggable(false)
    })
    if (brushMode.value === 'brush' || 'eraser') {
      //画一个圆
      const pos = stage.value.getStage().getPointerPosition()
      brush.value.x = pos.x / configKonva.value.scale.x
      brush.value.y = pos.y / configKonva.value.scale.x
      brush.value.globalCompositeOperation = brushMode.value === 'brush' ? 'source-over' : 'destination-out'
      const circle = new Konva.Circle(brush.value);
      console.log(pos)
      maskLayer.value.getStage().add(circle);
    }
    // if (brushMode.value === 'line') {
    //   //画一条线
    //   const pos = stage.value.getStage().getPointerPosition()
    //   configLine.value.points = [pos.x, pos.y, pos.x, pos.y]
    //   // layer2.value.getStage().add(new Konva.Line(configLine.value))
    // }
    stage.value.getStage().on('mousemove', handleStageMouseMove)
    stage.value.getStage().on('touchmove', handleStageMouseMove)
    // layer.value.draw();
  } else {
    //选中-变换模式
    baseLayer.value.getStage().children.forEach(item => {
      item.draggable(true)
    })
    if (e.target === e.target.getStage()) {
      selectedShapeName.value = '';
      // updateTransformer();
      return;
    }
    // clicked on transformer - do nothing
    const clickedOnTransformer =
        e.target.getParent().className === 'Transformer';
    if (clickedOnTransformer) {
      return;
    }
    // find clicked rect by its name
    const name = e.target.name();
    //隐藏maskLayer
    // maskLayer.value.getStage().hide()
    const node = baseLayer.value.getStage().findOne('.' + name);
    console.log('选中的对象', node)
    if (node) {
      selectedShapeName.value = name;
    } else {
      selectedShapeName.value = '';
    }
    updateTransformer();
  }
}
const handleStageMouseMove = (e) => {
  console.log('event', e)
  if (freeDraw.value) {
    if (brushMode.value === 'brush' || 'eraser') {
      console.log(e)
      // prevent scrolling on touch devices
      e.evt.preventDefault();
      const pos = stage.value.getStage().getPointerPosition();
      brush.value.x = pos.x / configKonva.value.scale.x
      brush.value.y = pos.y / configKonva.value.scale.x
      brush.value.globalCompositeOperation = brushMode.value === 'brush' ? 'source-over' : 'destination-out'
      const _brush = new Konva.Circle(brush.value)
      maskLayer.value.getStage().add(_brush)
      // const circle = new Konva.Circle(brush.value);
      // layer2.value.getStage().add(circle);
    }

  } else {

  }
}
const handleStageMouseUp = () => {
  if (freeDraw.value) {
    if (brushMode.value === 'line') {
    } else {
      stage.value.getStage().off('mousemove', handleStageMouseMove)
      stage.value.getStage().off('touchmove', handleStageMouseMove)
    }
  } else {
    if (editMode.value === 'clip') {
      stage.value.getStage().off('mousemove', handleStageMouseMove)
      stage.value.getStage().off('touchmove', handleStageMouseMove)
    }
  }
}


const updateTransformer = () => {
  // here we need to manually attach or detach Transformer node
  const transformerNode = transformer.value.getNode();
  const stage = transformerNode.getStage();
  // selectedShapeName.value = transformerNode.node()?.name() || '';//??
  console.log(stage)
  const selectedNode = stage.findOne('.' + selectedShapeName.value);
  console.log(selectedShapeName.value, selectedNode)
  // do nothing if selected node is already attached
  if (selectedNode === transformerNode.node()) {
    return;
  }
  if (selectedNode) {
    // attach to another node
    transformerNode.nodes([selectedNode]);
  } else {
    // remove transformer
    transformerNode.nodes([]);
  }
}

const handleDownloadLayer = () => {
  const data = baseLayer.value.getStage().toDataURL()
  console.log(data)
  downloadURI(data, 'layer.png');
}
const downloadURI = (uri, name) => {
  const link = document.createElement('a');
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}


/**
 * 适应父窗口
 */
const handleFitStageIntoParentContainer = () => {
  // now we need to fit stage into parent container

  const containerWidth = stage.value.getStage().container().offsetWidth
  // but we also make the full scene visible
  // so we need to scale all objects on canvas
  const scale = containerWidth / sceneWidth;
  configKonva.value.width = sceneWidth * scale
  configKonva.value.height = sceneHeight * scale
  configKonva.value.scale = {x: scale, y: scale}
  console.log('窗口变化，重新调整stage的大小', configKonva.value.width, configKonva.value.height)
}
//监听窗口大小改变
if (process.client) {
  window.onresize = () => {
    handleFitStageIntoParentContainer()
  }
}
/**
 * 画板自适应元素大小
 */
const handleFitStageIntoChildContainer = (options?:{showWaring?:boolean}) => {
  // now we need to fit stage into parent container
  const containerWidth = stage.value.getStage().container().offsetWidth
  if (baseLayer.value.getStage().children.length === 1) {
    const node = baseLayer.value.getStage().children[0]
    node.x(0)
    node.y(0)
    node.scaleX(1)
    node.scaleY(1)
    const imageWidth = node.image().width
    const imageHeight = node.image().height
    const scale = containerWidth / imageWidth
    configKonva.value.width = containerWidth
    configKonva.value.height = imageHeight * scale
    configKonva.value.scale = {x: scale, y: scale}
  } else {
    if(options?.showWaring){
      useSnackbarStore().showWarningMessage('画板内存在多个元素，无法自适应，请删除多余元素')
    }
  }
}

interface Model {
  image_path_origin: string
  image_path_mask: string
}

const model = defineModel<Model>({
  default: {
    image_path_origin: '',
    image_path_mask: ''
  }
})

const handleUploadBaseLayer = async () => {
  const _url = await handleuploadLayer(baseLayer.value)
  if (_url) {
    model.value = {
      ...model.value,
      image_path_origin: _url
    }
    return _url
  }
}
const handleUploadMaskLayer = async () => {
  const _url = await handleuploadLayer(maskLayer.value)
  if (_url) {
    model.value = {
      ...model.value,
      image_path_mask: _url
    }
    return _url
  }
}
//将baseLayder上传到服务器
const handleuploadLayer = async (layer: any) => {
  const blob = await layer.getStage().toBlob({
    pixelRatio: 1 / configKonva.value.scale.x
  })
  const file = await blobtoFile(blob, 'image')
  const url = await useUtilsUploadFileToOSS(file, 'image')
  if (url) {
    console.log('上传成功', url)
    return url
  }
}

defineExpose({
  handleUploadBaseLayer,
  handleUploadMaskLayer
})

const handleChangeBushModel = (mode:DrawMode) =>{
  console.log('切换笔刷模式:'+mode)
  freeDraw.value=true
  brushMode.value=mode
  //将masklayer调整到上层
  maskLayer.value.getStage().moveToTop()
}
const handleChangeEditMode=(mode:EditMode)=>{
  freeDraw.value=false
  //将masklayer调整到下层
  maskLayer.value.getStage().moveToBottom()
  editMode.value=mode
}
const handleClearOutMaskLayer=()=>{
  maskLayer.value.getStage().destroyChildren()
}
const handleClearOutBaseLayer=()=>{
  baseLayer.value.getStage().destroyChildren()
}

</script>

<template>
  <v-row>
    <v-col cols="12" class="">
      <v-card class="ma-2 grid-background-lg">
        <a-float-button-group trigger="click" type="primary" :style="{ top: '100px',right:'0px',position:'absolute' }">
          <template #icon>
<!--            <CustomerServiceOutlined/>-->
            <v-icon size="20">mdi-dots-horizontal</v-icon>

          </template>
          <a-float-button @click="handleChangeEditMode('transform')">
            <template #icon>
<!--              <DragOutlined/>-->
              <v-icon size="20">mdi-cursor-move</v-icon>
            </template>
          </a-float-button>
          <a-float-button @click="handleChangeBushModel('brush')">
            <template #icon>
<!--              <HighlightOutlined />-->
              <v-icon size="20">mdi-brush</v-icon>
            </template>
          </a-float-button>
          <a-float-button @click="handleChangeBushModel('eraser')">
            <template #icon>
              <v-icon size="20">mdi-eraser</v-icon>
            </template>
          </a-float-button>
          <a-float-button @click="handleClearOutMaskLayer">
            <template #icon>
              <v-icon size="20">mdi-brush-off</v-icon>
            </template>
          </a-float-button>
        </a-float-button-group>

        <v-stage ref="stage" :config="configKonva" @mousedown="handleStageMouseDown" @mouseup="handleStageMouseUp"
                 @touchstart="handleStageMouseDown">

          <v-layer :config="baseLayerConfig" ref="baseLayer">
          </v-layer>
          <v-layer ref="maskLayer" :config="maskLayerConfig"></v-layer>
          <v-layer ref="handleLayer" :config="handleLayerConfig">
            <v-transformer ref="transformer"/>
          </v-layer>
        </v-stage>
        <UploadButton v-model="uploadurl">
          <a-float-button type="primary" :style="{top:'0px',right:'0px',position:'absolute'}" @click="">
            <template #icon>
              <UploadOutlined/>
            </template>
          </a-float-button>
        </UploadButton>
        <a-float-button type="primary" :style="{top:'50px',right:'0px',position:'absolute'}" @click="handleFitStageIntoChildContainer({showWaring:true})">
          <template #icon>
            <v-icon size="20">mdi-fullscreen</v-icon>
          </template>
        </a-float-button>
      </v-card>
    </v-col>
  </v-row>
<!--  <v-btn @click="handleFitStageIntoChildContainer">画板自适应</v-btn>-->
<!--  <v-btn @click="handleDownloadLayer">下载图层</v-btn>-->
<!--  <v-btn @click="handleUploadBaseLayer">上传图层到服务器</v-btn>-->
<!--  <v-btn @click="handleUploadMaskLayer">上传遮罩到服务器</v-btn>-->
<!--  <v-btn @click="freeDraw=!freeDraw">{{ freeDraw ? '画布模式' : '自由模式' }}</v-btn>-->
<!--  <v-btn @click="brushMode='brush'">画刷</v-btn>-->
<!--  <v-btn @click="brushMode='line'">线</v-btn>-->
<!--  <v-btn @click="brushMode='eraser'">橡皮</v-btn>-->

  <!--  确认裁剪-->

</template>

<style scoped lang="scss">
.grid-background-lg {
  background: linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  ),
  linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  );
  /* 背景大小必须小于盒子的大小 */
  background-size: 40px 40px;
  /* 第二种渐变的偏移必须为为背景大小的一半 */
  background-position: 0 0, 20px 20px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.grid-background-sm {
  background: linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  ),
  linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  );
  /* 背景大小必须小于盒子的大小 */
  background-size: 20px 20px;
  /* 第二种渐变的偏移必须为为背景大小的一半 */
  background-position: 0 0, 10px 10px;

}
</style>